package ord2.indexer;

import java.io.File;
import java.util.LinkedList;
import java.util.List;
import ord2.core.Parameter;

/**
 * This class specific a indexer that will not block util indexing finishs. It will
 * create a separeted thread that will run <code>processDocuments</code>
 * @see Indexer#processDocuments()
 * @see NonBlockingIndexerListener
 * @see BlockingAbstractIndexer
 *
 * @author José Ivan
 * @author Edviges
 *
 */
public abstract class NonBlockingAbstractIndexer extends AbstractIndexer
                                implements NonBlockingIndexer {
    
    private final LinkedList<NonBlockingIndexerListener> listeners =
            new LinkedList<NonBlockingIndexerListener>();
    
    /**
     * @see AbstractIndexer#AbstractIndexer(ord2.core.Parameter[]) 
     */
    public NonBlockingAbstractIndexer(Parameter[] pars) {
        
        super(pars);
    }
    
    /**
     * @see AbstractIndexer#AbstractIndexer() 
     */
    public NonBlockingAbstractIndexer() {
        
        super();
    }
    
    /**
     * @see AbstractIndexer#AbstractIndexer(java.io.File[], ord2.core.Parameter[]) 
     */
    public NonBlockingAbstractIndexer(File[] docs, Parameter[] pars) {
        
        super(docs, pars);
    }
    
    @Override
    public final void addIndexerListener(NonBlockingIndexerListener list) {
        
        if (list != null) {
            
            this.listeners.add(list);
        }
    }
    
    @Override
    public final boolean processDocuments() {
        
        if (!this.isProcessing()) {

            final NonBlockingAbstractIndexer index = this;
            this.notifyStartProcessing();
            (new Thread() {
                
                @Override
                public void run() {
                   
                    Exception e = index.process();
                    index.notifyStopProcessing();
                    index.notifyListeners(e, index);
                }
                
            }).start();
            
            return true;
        }
        
        return false;
    }
    
    /**
     * This method should be implemented with indexing operations. This method will
     * be called when <code>processDocuments<code> is called. It must return a
     * instance of Exception that will tell that a error occured or null otherwise.
     * @return Instance of Exception that caused a error in indexing process.
     */
    protected abstract Exception process();
    
    private void notifyListeners(Exception e, Indexer index) {
        
        for (NonBlockingIndexerListener l : this.listeners) {
            
            l.indexingCompleted(index, e);
        }
    }
}
